package com.zenithmind.note.pojo.entity;

import com.zenithmind.common.base.BaseEntity;
import com.zenithmind.note.pojo.enums.ShareType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 笔记分享实体类
 * 遵循面向对象设计原则：
 * 1. 单一职责：只负责分享相关的数据和业务逻辑
 * 2. 封装性：提供业务方法控制分享状态和有效性
 * 3. 不变性：分享码一旦生成不可修改
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "笔记分享实体", description = "笔记分享实体")
public class NoteShare extends BaseEntity {

    @Schema(description = "笔记ID")
    @NotNull(message = "笔记ID不能为空")
    private String noteId;

    @Schema(description = "分享用户ID")
    @NotNull(message = "用户ID不能为空")
    private String userId;

    @Schema(description = "分享类型")
    @NotNull(message = "分享类型不能为空")
    private Integer shareType;

    @Schema(description = "分享码，用于生成访问链接")
    private String shareCode;

    @Schema(description = "被查看次数")
    private Integer shareCount;

    @Schema(description = "状态：0-失效，1-有效")
    private Integer status;

    @Schema(description = "过期时间，NULL表示永不过期")
    private LocalDateTime expireTime;

    // ==================== 业务方法 ====================

    /**
     * 获取分享类型枚举
     *
     * @return 分享类型
     */
    public ShareType getShareTypeEnum() {
        return ShareType.fromCode(this.shareType);
    }

    /**
     * 设置分享类型
     *
     * @param shareType 分享类型
     */
    public void setShareTypeEnum(ShareType shareType) {
        this.shareType = shareType != null ? shareType.getCode() : null;
    }

    /**
     * 判断分享是否有效
     *
     * @return 是否有效
     */
    public boolean isValid() {
        // 检查状态
        if (this.status == null || this.status != 1) {
            return false;
        }

        // 检查是否过期
        if (this.expireTime != null && this.expireTime.isBefore(LocalDateTime.now())) {
            return false;
        }

        return true;
    }

    /**
     * 判断分享是否已过期
     *
     * @return 是否已过期
     */
    public boolean isExpired() {
        return this.expireTime != null && this.expireTime.isBefore(LocalDateTime.now());
    }

    /**
     * 判断是否为永久分享
     *
     * @return 是否永久
     */
    public boolean isPermanent() {
        return this.expireTime == null;
    }

    /**
     * 判断是否可以被访问
     *
     * @return 是否可访问
     */
    public boolean isAccessible() {
        return isValid() && !isExpired();
    }

    /**
     * 生成分享码
     *
     * @return 分享码
     */
    public String generateShareCode() {
        if (this.shareCode == null || this.shareCode.trim().isEmpty()) {
            this.shareCode = UUID.randomUUID().toString().replace("-", "");
        }
        return this.shareCode;
    }

    /**
     * 增加访问次数
     */
    public void incrementViewCount() {
        if (this.shareCount == null) {
            this.shareCount = 0;
        }
        this.shareCount++;
    }

    /**
     * 激活分享
     */
    public void activate() {
        this.status = 1;
    }

    /**
     * 失效分享
     */
    public void deactivate() {
        this.status = 0;
    }

    /**
     * 设置过期时间
     *
     * @param expireTime 过期时间
     */
    public void setExpireTime(LocalDateTime expireTime) {
        if (expireTime != null && expireTime.isBefore(LocalDateTime.now())) {
            throw new IllegalArgumentException("过期时间不能早于当前时间");
        }
        this.expireTime = expireTime;
    }

    /**
     * 设置永久有效
     */
    public void setPermanent() {
        this.expireTime = null;
    }

    /**
     * 初始化新分享的默认值
     */
    public void initializeDefaults() {
        if (this.shareCount == null) {
            this.shareCount = 0;
        }
        if (this.status == null) {
            this.status = 1; // 默认有效
        }
        generateShareCode();
    }

    /**
     * 判断是否为社交媒体分享
     *
     * @return 是否为社交媒体分享
     */
    public boolean isSocialMediaShare() {
        ShareType type = getShareTypeEnum();
        return type != null && type.isSocialMedia();
    }
}